home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / pvm34b3.zip / pvm34b3 / pvm3 / src / msgbox.c < prev    next >
C/C++ Source or Header  |  1997-07-22  |  13KB  |  586 lines

  1.  
  2. static char rcsid[] =
  3.     "$Id: msgbox.c,v 1.17 1997/06/27 17:32:30 pvmsrc Exp $";
  4.  
  5. /*
  6.  *         PVM version 3.4:  Parallel Virtual Machine System
  7.  *               University of Tennessee, Knoxville TN.
  8.  *           Oak Ridge National Laboratory, Oak Ridge TN.
  9.  *                   Emory University, Atlanta GA.
  10.  *      Authors:  J. J. Dongarra, G. E. Fagg, M. Fischer
  11.  *          G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci,
  12.  *         P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam
  13.  *                   (C) 1997 All Rights Reserved
  14.  *
  15.  *                              NOTICE
  16.  *
  17.  * Permission to use, copy, modify, and distribute this software and
  18.  * its documentation for any purpose and without fee is hereby granted
  19.  * provided that the above copyright notice appear in all copies and
  20.  * that both the copyright notice and this permission notice appear in
  21.  * supporting documentation.
  22.  *
  23.  * Neither the Institutions (Emory University, Oak Ridge National
  24.  * Laboratory, and University of Tennessee) nor the Authors make any
  25.  * representations about the suitability of this software for any
  26.  * purpose.  This software is provided ``as is'' without express or
  27.  * implied warranty.
  28.  *
  29.  * PVM version 3 was funded in part by the U.S. Department of Energy,
  30.  * the National Science Foundation and the State of Tennessee.
  31.  */
  32.  
  33. /*
  34.  *    msgbox.c
  35.  *
  36.  *    Message mailbox database.
  37.  *
  38. $Log: msgbox.c,v $
  39.  * Revision 1.17  1997/06/27  17:32:30  pvmsrc
  40.  * Updated for WIN32 header files & Authors.
  41.  *
  42.  * Revision 1.16  1997/05/07  21:23:54  pvmsrc
  43.  * Fixed manual packing of class name lengths.
  44.  *     - no longer necessary with (pvm)upkstralloc() usage.
  45.  * Fixed bug:
  46.  *     - only free pattbuf if !pattglob...  D-Oh!
  47.  *
  48.  * Revision 1.15  1997/05/05  18:17:49  pvmsrc
  49.  * Added new pvmregex.o targets (part of ./regex stuff).
  50.  *     - extracted mb_names() regex usage to new pvm/regex routines:
  51.  *         void *pvmcompileregex __ProtoGlarp__ (( char * ));
  52.  *         int pvmmatchregex __ProtoGlarp__ (( void *, char * ));
  53.  *         void pvmfreeregex __ProtoGlarp__ (( void ** ));
  54.  *
  55.  * Revision 1.14  1997/05/02  19:44:38  pvmsrc
  56.  * Added GNU Regex Stuff:
  57.  *     - Makefile targets for regex.o
  58.  *     - usage in mb_names() / msgbox.c
  59.  *
  60.  * Revision 1.13  1997/05/02  14:54:18  pvmsrc
  61.  * Implemented guts of pvm_getmboxinfo():
  62.  *     - user library side sends pattern & receives back / allocs array.
  63.  *     - at pvmd side mb_names() searches class list for matching pattern,
  64.  *         count up # of entries, and pack up struct info.
  65.  *         (Note:  does not yet use GNU regex stuff...)
  66.  *
  67.  * Revision 1.12  1997/04/10  17:53:54  pvmsrc
  68.  * Externalized me_new()...
  69.  *     - for WT_RECVINFO usage...
  70.  *
  71.  * Revision 1.11  1997/04/08  20:06:33  pvmsrc
  72.  * Un-static-ed me_free().
  73.  *     - so ddpro.c can use it...  D-Oh.
  74.  *
  75.  * Revision 1.10  1997/04/08  19:57:52  pvmsrc
  76.  * Promoted mbox static "classes" to public global "pvmmboxclasses".
  77.  *     - so pvmd can spank mboxes in ddpro.c...  :-Q
  78.  *     - renamed everywhere, moved decl / extern to global.[ch].
  79.  *
  80.  * Revision 1.9  1997/04/08  19:41:11  pvmsrc
  81.  * Added me_savetid to pvmmentry struct.
  82.  *     - for keeping track of original owner on persistent mboxes.
  83.  *     - allows more careful cleanup in a system reset, set me_tid to 0
  84.  *         but save original tid in me_savetid first...  :-)
  85.  *
  86.  * Revision 1.8  1997/04/08  18:45:20  pvmsrc
  87.  * Yanked out internal struct defns for mclass & mentry.
  88.  *     - replaced with msgbox.h header, and pvmmclass / pvmmentry structs.
  89.  *
  90.  * Revision 1.7  1997/04/08  17:53:25  pvmsrc
  91.  * Added new mb_tidy_reset() routine.
  92.  *     - triggered by task exit during a system reset (when persistent
  93.  *         mbox entries are owned by task).
  94.  *     - clear out any persistent mboxes owned by task, or any others
  95.  *         that have already been cleared.
  96.  *
  97.  * Revision 1.6  1997/04/01  16:39:39  pvmsrc
  98.  * Oops...  PvmMboxOverwritable -> PvmMboxOverWritable...  D-Oh.
  99.  *
  100.  * Revision 1.5  1997/04/01  16:19:25  pvmsrc
  101.  * Modified mbox internals to properly handle new flags syntax.
  102.  *     - pvm_putinfo():
  103.  *         * PvmMboxMultiInstance = if index 0 is in use, stick in
  104.  *             first available higher index.
  105.  *         * PvmMboxOverwritable = allow anyone to overwrite or delete
  106.  *             the given mbox entry.
  107.  *         * PvmMboxPersistent = do not remove mailbox on task exit,
  108.  *             allow only PVMD to delete on reset (after task exit only).
  109.  *     - pvm_recvinfo():
  110.  *         * PvmMboxReadAndDelete = if entry is owned by task or is
  111.  *             overwritable, read entry and atomically delete, else fail.
  112.  *         * PvmMboxFirstAvail = if entry not present at given index,
  113.  *             return next entry by index, else fail.
  114.  *
  115.  * Revision 1.4  1997/01/28  19:26:54  pvmsrc
  116.  * New Copyright Notice & Authors.
  117.  *
  118.  * Revision 1.3  1996/10/24  21:04:48  pvmsrc
  119.  * Moved #include of "global.h" down below other headers:
  120.  *     - need to have all of the structures / types declared before
  121.  *         the globals can be declared...
  122.  *
  123.  * Revision 1.2  1996/09/23  23:32:16  pvmsrc
  124.  * Initial Creation - original msgbox.c.
  125.  *
  126.  */
  127.  
  128.  
  129. #include <stdio.h>
  130. #ifdef NEEDMENDIAN
  131. #include <machine/endian.h>
  132. #endif
  133. #ifdef NEEDENDIAN
  134. #include <endian.h>
  135. #endif
  136. #ifdef NEEDSENDIAN
  137. #include <sys/endian.h>
  138. #endif
  139. #ifndef WIN32
  140. #include <rpc/types.h>
  141. #include <rpc/xdr.h>
  142. #else 
  143. #include "..\xdr\types.h"
  144. #include "..\xdr\xdr.h"
  145. #endif
  146.  
  147. #ifdef    SYSVSTR
  148. #include <string.h>
  149. #else
  150. #include <strings.h>
  151. #endif
  152. #include <pvm3.h>
  153. #include "pvmalloc.h"
  154. #include "listmac.h"
  155. #include "pmsg.h"
  156. #include "msgbox.h"
  157. #include "global.h"
  158.  
  159. void *pvmcompileregex __ProtoGlarp__ (( char * ));
  160. int pvmmatchregex __ProtoGlarp__ (( void *, char * ));
  161. void pvmfreeregex __ProtoGlarp__ (( void ** ));
  162.  
  163.  
  164. /***************
  165.  **  Globals  **
  166.  **           **
  167.  ***************/
  168.  
  169. extern int pvmdebmask;                    /* from pvmd.c */
  170.  
  171. /***************
  172.  **  Private  **
  173.  **           **
  174.  ***************/
  175.  
  176. struct pvmmentry *
  177. me_new(ind)
  178.     int ind;
  179. {
  180.     struct pvmmentry *ep;
  181.  
  182.     if (ep = TALLOC(1, struct pvmmentry, "pvmmentry")) {
  183.         ep->me_link = ep->me_rlink = ep;
  184.         ep->me_tid = 0;
  185.         ep->me_savetid = 0;
  186.         ep->me_flags = PvmMboxDefault;
  187.         ep->me_msg = 0;
  188.         ep->me_ind = ind;
  189.     }
  190.     return ep;
  191. }
  192.  
  193.  
  194. static struct pvmmclass *
  195. mc_new(name)
  196.     char *name;
  197. {
  198.     struct pvmmclass *np;
  199.  
  200.     if (np = TALLOC(1, struct pvmmclass, "pvmmclass")) {
  201.         if (name) {
  202.             np->mc_name = STRALLOC(name);
  203.             np->mc_ent = me_new(-1);
  204.             LISTPUTBEFORE(pvmmboxclasses, np, mc_link, mc_rlink);
  205.  
  206.         } else {
  207.             np->mc_link = np->mc_rlink = np;
  208.             np->mc_name = 0;
  209.             np->mc_ent = 0;
  210.         }
  211.     }
  212.     return np;
  213. }
  214.  
  215.  
  216. int
  217. me_free(np, ep)
  218.     struct pvmmclass *np;
  219.     struct pvmmentry *ep;
  220. {
  221.     LISTDELETE(ep, me_link, me_rlink);
  222.     pmsg_unref(ep->me_msg);
  223.     PVM_FREE(ep);
  224.     if (np->mc_ent->me_link == np->mc_ent) {
  225.         LISTDELETE(np, mc_link, mc_rlink);
  226.         PVM_FREE(np->mc_name);
  227.         PVM_FREE(np->mc_ent);
  228.         PVM_FREE(np);
  229.     }
  230.     return 0;
  231. }
  232.  
  233.  
  234. static struct pvmmclass *
  235. mc_find(name)
  236.     char *name;
  237. {
  238.     struct pvmmclass *np;
  239.  
  240.     for (np = pvmmboxclasses->mc_link; np != pvmmboxclasses;
  241.             np = np->mc_link)
  242.         if (!strcmp(np->mc_name, name))
  243.             return np;
  244.     return (struct pvmmclass *)0;
  245. }
  246.  
  247.  
  248. int
  249. mb_init()
  250. {
  251.     pvmmboxclasses = mc_new((char*)0);
  252.     return 0;
  253. }
  254.  
  255.  
  256. int
  257. mb_insert(tid, name, req, flags, mp)
  258.     int tid;                /* owner task */
  259.     char *name;                /* class name */
  260.     int req;                /* index requested or -1 for lowest avail */
  261.     int flags;
  262.     struct pmsg *mp;        /* message to store */
  263. {
  264.     struct pvmmclass *np;
  265.     struct pvmmentry *ep;
  266.     struct pvmmentry *ep2 = 0;
  267.  
  268.     if (!(np = mc_find(name)))
  269.         if (!(np = mc_new(name)))
  270.             return PvmNoMem;
  271.  
  272.     for (ep = np->mc_ent->me_link; ep != np->mc_ent; ep = ep->me_link)
  273.         if (ep->me_ind >= req)
  274.             break;
  275.  
  276.     /* default insert is "locked"... */
  277.  
  278.     if (flags & PvmMboxMultiInstance) {
  279.         for (; ep != np->mc_ent; ep = ep->me_link) {
  280.             if (ep->me_ind != req)
  281.                 break;
  282.             if ( (ep->me_flags & PvmMboxOverWritable)
  283.                     || tid == ep->me_tid ) {
  284.                 ep2 = ep;
  285.                 break;
  286.             }
  287.             req = ep->me_ind + 1;
  288.         }
  289.     } else {
  290.         if (ep->me_ind == req) {
  291.             if ( !(ep->me_flags & PvmMboxOverWritable)
  292.                     && tid != ep->me_tid) {
  293.                 return PvmDenied;
  294.             }
  295.             ep2 = ep;
  296.         }
  297.     }
  298.  
  299.     if (ep2) {
  300.         ep = ep2->me_link;
  301.         LISTDELETE(ep2, me_link, me_rlink);
  302.         pmsg_unref(ep2->me_msg);
  303.         PVM_FREE(ep2);
  304.     }
  305.     ep2 = me_new(req);
  306.     ep2->me_tid = tid;
  307.     ep2->me_flags = flags;
  308.     ep2->me_msg = mp;
  309.     LISTPUTBEFORE(ep, ep2, me_link, me_rlink);
  310.  
  311.     return req;
  312. }
  313.  
  314.  
  315. int
  316. mb_delete(tid, name, req, flags)
  317.     int tid;                /* owner task */
  318.     char *name;                /* class name */
  319.     int req;                /* index */
  320.     int flags;                /* options */
  321. {
  322.     struct pvmmclass *np;
  323.     struct pvmmentry *ep = 0;
  324.  
  325.     if (np = mc_find(name)) {
  326.         for (ep = np->mc_ent->me_link; ep != np->mc_ent;
  327.                 ep = ep->me_link) {
  328.             if (ep->me_ind == req)
  329.                 break;
  330.         }
  331.         if (ep == np->mc_ent)
  332.             ep = 0;
  333.     }
  334.  
  335.     if (!ep)
  336.         return PvmNotFound;
  337.  
  338.     if ( !(ep->me_flags & PvmMboxOverWritable) && tid != ep->me_tid )
  339.         return PvmDenied;
  340.  
  341.     req = ep->me_ind;
  342.     me_free(np, ep);
  343.  
  344.     return req;
  345. }
  346.  
  347.  
  348. int
  349. mb_lookup(tid, name, req, flags, mpp)
  350.     int tid;                /* owner task */
  351.     char *name;                /* class name */
  352.     int req;                /* index requested or -1 for first avail */
  353.     int flags;
  354.     struct pmsg **mpp;        /* message return */
  355. {
  356.     struct pvmmclass *np;
  357.     struct pvmmentry *ep = 0;
  358.  
  359.     if (np = mc_find(name)) {
  360.         for (ep = np->mc_ent->me_link; ep != np->mc_ent;
  361.                 ep = ep->me_link) {
  362.             if (ep->me_ind >= req)
  363.                 break;
  364.         }
  365.         if (ep == np->mc_ent)
  366.             ep = 0;
  367.         else if (!(flags & PvmMboxFirstAvail) && ep->me_ind != req)
  368.             ep = 0;
  369.     }
  370.  
  371.     if (ep) {
  372.         if ( flags & PvmMboxReadAndDelete ) {
  373.             if ( (ep->me_flags & PvmMboxOverWritable)
  374.                     || tid == ep->me_tid ) {
  375.                 req = ep->me_ind;
  376.                 ep->me_msg->m_ref++;
  377.                 *mpp = ep->me_msg;
  378.                 me_free(np, ep);
  379.             } else {
  380.                 req = PvmDenied;
  381.                 *mpp = (struct pmsg *) NULL;
  382.             }
  383.         } else {
  384.             req = ep->me_ind;
  385.             ep->me_msg->m_ref++;
  386.             *mpp = ep->me_msg;
  387.         }
  388.     } else
  389.         req = PvmNotFound;
  390.  
  391.     return req;
  392. }
  393.  
  394.  
  395. int
  396. mb_names(tid, pattern, mp)
  397.     int tid;
  398.     char *pattern;
  399.     struct pmsg *mp;
  400. {
  401.     void *pattbuff;
  402.  
  403.     struct pvmmclass *np;
  404.     struct pvmmentry *ep;
  405.  
  406.     int pattglob = 0;
  407.     int cnt;
  408.  
  409.     /* Check for "*" Global Match Pattern */
  410.  
  411.     if ( !strcmp( pattern, "*" ) )
  412.         pattglob = 1;
  413.  
  414.     /* Compile Regular Expression */
  415.  
  416.     if ( !pattglob )
  417.         pattbuff = pvmcompileregex( pattern );
  418.  
  419.     /* Count # of Classes */
  420.  
  421.     cnt = 0;
  422.  
  423.     for ( np = pvmmboxclasses->mc_link; np != pvmmboxclasses;
  424.             np = np->mc_link )
  425.     {
  426.         if ( pattglob
  427.                 || ( ( pattbuff ) ?
  428.                     ( pvmmatchregex( pattbuff, np->mc_name ) )
  429.                     : ( !strcmp( pattern, np->mc_name ) ) ) )
  430.         {
  431.             cnt++;
  432.         }
  433.     }
  434.  
  435.     pkint( mp, cnt );
  436.  
  437.     /* Pack Class Info */
  438.  
  439.     for ( np = pvmmboxclasses->mc_link; np != pvmmboxclasses;
  440.             np = np->mc_link )
  441.     {
  442.         if ( pattglob
  443.                 || ( ( pattbuff ) ?
  444.                     ( pvmmatchregex( pattbuff, np->mc_name ) )
  445.                     : ( !strcmp( pattern, np->mc_name ) ) ) )
  446.         {
  447.             pkstr( mp, np->mc_name );
  448.  
  449.             /* Count # of Entries */
  450.  
  451.             cnt = 0;
  452.  
  453.             for ( ep = np->mc_ent->me_link; ep != np->mc_ent;
  454.                     ep = ep->me_link )
  455.                 cnt++;
  456.  
  457.             pkint( mp, cnt );
  458.  
  459.             /* Pack Entry Info */
  460.  
  461.             for ( ep = np->mc_ent->me_link; ep != np->mc_ent;
  462.                     ep = ep->me_link )
  463.             {
  464.                 pkint( mp, ep->me_ind );
  465.                 pkint( mp, ep->me_tid );
  466.                 pkint( mp, ep->me_flags );
  467.             }
  468.         }
  469.     }
  470.  
  471.     if ( !pattglob && pattbuff )
  472.         pvmfreeregex( &pattbuff );
  473.  
  474.     return 0;
  475. }
  476.  
  477.  
  478. int
  479. mb_dump(np)
  480.     struct pvmmclass *np;
  481. {
  482.     struct pvmmentry *ep;
  483.  
  484.     pvmlogprintf("<%s>\n", np->mc_name);
  485.     for (ep = np->mc_ent->me_link; ep != np->mc_ent; ep = ep->me_link) {
  486.         pvmlogprintf("%d (0x%x): owner 0x%x (was 0x%x) flags %d\n",
  487.                 ep->me_ind, ep->me_ind, ep->me_tid, ep->me_savetid,
  488.                 ep->me_flags);
  489.         pmsg_dump(ep->me_msg, 2);
  490.     }
  491.     return 0;
  492. }
  493.  
  494.  
  495. int
  496. mb_dumpall()
  497. {
  498.     struct pvmmclass *np;
  499.  
  500.     pvmlogerror("mb_dumpall():\n");
  501.     for (np = pvmmboxclasses->mc_link; np != pvmmboxclasses;
  502.             np = np->mc_link)
  503.         mb_dump(np);
  504.     return 0;
  505. }
  506.  
  507.  
  508. /*    mb_tidy()
  509. *
  510. *    Task has exited.
  511. *    Remove any non-sticky entries owned by it.
  512. *    Remove its tid as owner for sticky entries and reset Lock.
  513. */
  514.  
  515. int
  516. mb_tidy(tid)
  517.     int tid;
  518. {
  519.     struct pvmmclass *np, *np2;
  520.     struct pvmmentry *ep, *ep2;
  521.  
  522.     if (!tid)
  523.         return 0;
  524.  
  525.     if (pvmdebmask & PDMMBOX)
  526.         pvmlogprintf("mb_tidy() tid 0x%x\n", tid);
  527.  
  528.     for (np = pvmmboxclasses->mc_link; np != pvmmboxclasses; np = np2) {
  529.         np2 = np->mc_link;
  530.         for (ep = np->mc_ent->me_link; ep != np->mc_ent; ep = ep2) {
  531.             ep2 = ep->me_link;
  532.             if (ep->me_tid == tid) {
  533.                 if (ep->me_flags & PvmMboxPersistent) {
  534.                     ep->me_savetid = ep->me_tid;
  535.                     ep->me_tid = 0;
  536.                 } else {
  537.                     me_free(np, ep);
  538.                     if (np2->mc_rlink != np)
  539.                         break;
  540.                 }
  541.             }
  542.         }
  543.     }
  544.     return 0;
  545. }
  546.  
  547.  
  548. /*    mb_tidy_reset()
  549. *
  550. *    Task has exited during a system reset.
  551. *    Remove any persistent entries owned by it, and any other
  552. *    persistent entries that have already been cleared.
  553. */
  554.  
  555. int
  556. mb_tidy_reset(tid)
  557.     int tid;
  558. {
  559.     struct pvmmclass *np, *np2;
  560.     struct pvmmentry *ep, *ep2;
  561.  
  562.     if (!tid)
  563.         return 0;
  564.  
  565.     if (pvmdebmask & PDMMBOX)
  566.         pvmlogprintf("mb_tidy_reset() tid 0x%x\n", tid);
  567.  
  568.     for (np = pvmmboxclasses->mc_link; np != pvmmboxclasses; np = np2) {
  569.         np2 = np->mc_link;
  570.         for (ep = np->mc_ent->me_link; ep != np->mc_ent; ep = ep2) {
  571.             ep2 = ep->me_link;
  572.             /* mb_tidy() & mb_tidy_reset() could be in any order... */
  573.             if ( (ep->me_flags & PvmMboxPersistent)
  574.                     && ( ep->me_tid == tid
  575.                         || (!(ep->me_tid) && ep->me_savetid == tid) ) )
  576.             {
  577.                 me_free(np, ep);
  578.                 if (np2->mc_rlink != np)
  579.                     break;
  580.             }
  581.         }
  582.     }
  583.     return 0;
  584. }
  585.  
  586.